// Copyright (C) 2023 即时通讯网(52im.net) & Jack Jiang.
// The RainbowChat Project. All rights reserved.
// 
// 【本产品为著作权产品，合法授权后请放心使用，禁止外传！】
// 【本次授权给：<北京小羊驼科技有限公司>，授权编号：<NT231212144350>，代码指纹：<A.702363430.550>，技术对接人微信：<ID: wxid_wbyootvkdcgj22>】
// 【授权寄送：<收件：苏先生、地址：北京市大兴区北京密码西区6号楼1单元301、电话：18613885610、邮箱：bd@huiyuanxiang-inc.com>】
// 
// 【本系列产品在国家版权局的著作权登记信息如下】：
// 1）国家版权局登记名(简称)和权证号：RainbowChat    （证书号：软著登字第1220494号、登记号：2016SR041877）
// 2）国家版权局登记名(简称)和权证号：RainbowChat-Web（证书号：软著登字第3743440号、登记号：2019SR0322683）
// 3）国家版权局登记名(简称)和权证号：RainbowAV      （证书号：软著登字第2262004号、登记号：2017SR676720）
// 4）国家版权局登记名(简称)和权证号：MobileIMSDK-Web（证书号：软著登字第2262073号、登记号：2017SR676789）
// 5）国家版权局登记名(简称)和权证号：MobileIMSDK    （证书号：软著登字第1220581号、登记号：2016SR041964）
// * 著作权所有人：江顺/苏州网际时代信息科技有限公司
// 
// 【违法或违规使用投诉和举报方式】：
// 联系邮件：jack.jiang@52im.net
// 联系微信：hellojackjiang
// 联系QQ号：413980957
// 授权说明：http://www.52im.net/thread-1115-1-1.html
// 官方社区：http://www.52im.net
package com.x52im.mall;

import com.eva.android.HttpService4A;
import com.eva.android.HttpServiceFactory4A;
import com.eva.epc.common.dto.IdName;
import com.eva.epc.common.util.CommonUtils;
import com.eva.framework.dto.DataFromClient;
import com.eva.framework.dto.DataFromServer;

import java.util.Vector;

/**
 * RainbowChat的基于Java序列化对象传格式的HTTP接口读写工厂类。
 * 
 * @author Jack Jiang(http://www.52im.net/space-uid-1.html)
 * @since 1.0
 * @deprecated 201703月自RainbowChat v4.0起，以Java 序列化对象为传输格式的接口已逐步废弃，本类也随之慢慢被废弃，未来全部切为REST接口后将可删除之！
 */
// 本类的独立使用，是为了解决在程序崩溃时因android的全局变量机制（Exception时全局变量会被清除掉）
// 而导致的每调用getDefaultSertvice就会nullPointException从而导致连锁崩溃的问题
public class HttpServiceFactory4AImpl extends HttpServiceFactory4A
{
	private static HttpServiceFactory4AImpl instance = null;

	public static HttpServiceFactory4AImpl getInstance()
	{
		if(instance == null)
			instance = new HttpServiceFactory4AImpl();
		return instance;
	}

	@Override
	public HttpService4A getService(String serviceName)
	{
		HttpService4A serviceInstance = getServiceInstances().get(serviceName);
		if(serviceInstance == null)
		{
			if(DEFAULT_SERVICE_NAME.equals(serviceName))
			{
				serviceInstance = new HttpService4A(serviceName,MallGlobal.HTTP_SERVER_CONTROLLER_URL_ROOT,"MyController");
				addServices(MallGlobal.HTTP_SERVER_CONTROLLER_URL_ROOT, serviceInstance);
			}
		}
		return serviceInstance;
	}
//	
//	public static DataFromServer createDefaultFailed()
//	{
//		return new DataFromServer().setSuccess(false);
//	}


    
	/**
     * 客户端框架实用类.
     *
     * @author Jack Jiang(http://www.52im.net/space-uid-1.html)
     * @version 1.0
     * @deprecated 本类仅用于旧式的基于Java序列化对象数据传输方式，目前已不推荐使用这种方法，本类以后会删除！
     */
    public static class AToolKits //extends BaseUtils
    {
        /**
         * 获得数据库查询语句的结果.
         *
         * @param sql 查询语句
         * @return 返回的查询结果，如果DataFromServer.isSuccess()=true则一定会返回二维Vector<Vector>，
         * 否则返回null（可以据返回结果是否为null来判断是否执行成功了）
         * @see BaseUtils#queryDataRoot(HttpService4A, String)
         */
        public static Vector<Vector> queryData(HttpService4A httpService, String sql) {
            DataFromServer dfs = queryDataRoot(httpService, sql);
            if (isSuccess(dfs, null)) {
                //操作执行成功了但返回值是null，则让返回值是一个空的
                //2D vector，以方便用户区分结果是否执行成功
                if (dfs.getReturnValue() == null)
                    return new Vector();
                else
                    return (Vector<Vector>) dfs.getReturnValue();
            }
            return null;
        }
    
        // @see BaseUtils.queryDataRoot(..)
        public static DataFromServer queryDataRoot(HttpService4A httpService, String sql) {
            if (httpService == null) {
                throw new RuntimeException("queryDataRoot中httpService不可为null，请确认！");
            } else {
                DataFromServer dfs = httpService.sendObjToServer(DataFromClient.n().setProcessorId(0).setJobDispatchId(22).setNewData(sql));
                return dfs;
            }
        }
    
        /**
         * 从数据库获得相应条件数据集的第0行（不管结果集有多少行，其它行均会被忽略）.
         *
         * @param table  表名
         * @param column 要获得列名，可任意多列
         * @param where  查询条件，可为null
         * @return 没有查询到结果则返回null，否则取结果集的第0行
         * @see #queryItems(HttpService4A, String)
         */
        public static String[] queryItems(HttpService4A httpService, String table, String columns, String where) {
            return queryItems(httpService, constructGetSql(table, columns, where));
        }
    
        /**
         * 从数据库获得相应条件数据集的第0行（不管结果集有多少行，其它行均会被忽略）.
         *
         * @param SQLStr 要查询结果的SQL语句
         * @return 没有查询到结果则返回null，否则取结果集的第0行
         * @see #queryData(HttpService4A, String)
         */
        public static String[] queryItems(HttpService4A httpService, String SQLStr) {
            String[] ret = null;
            Vector<Vector> retVec = queryData(httpService, SQLStr);
            if (retVec != null && retVec.size() > 0) {
                Vector r = retVec.get(0);
                ret = new String[r.size()];
                r.toArray(ret);
            }
            return ret;
        }
    
        /**
         * 从指定的数据库表中获取数据，并组成IdName数组.
         *
         * @param table           取值表名，可以是合法的SQL语句中from后where前的任何样式，如形如：t1 a join t2 on t1.key=t2.key等
         * @param queryFieldNames 取值列名，一般为2个字段，前1个作为ID,后1个作为Name（特殊情况下：
         *                        当只有1列时，则认为该列即是ID也是Name；当列多于2个时其它列会被忽略）
         * @param where           where条件
         * @param other           其他条件，可以是诸如order by语句的任何合法SQL后缀.
         *                        (注：如果other参数是空的，则默认取第一列作自动排序列（order by [第1列]），如果真想排序则最好明确指明，因自动取会有这样的问题：
         *                        当第一列是一个函数且有不只一个参数则以逗号作为分隔符取第一列就不对了）)
         * @return 返回据指定语句查询出的数据构造成的IdName数组
         * @see #queryIdNames(String)
         */
        public static IdName[] queryIdNames(HttpService4A httpService
                , String table, String queryFieldNames, String where, String other) {
            //如果other参数是空的，则默认取第一列作自动排序列（order by [第1列]）
            String orderStr = CommonUtils.isStringEmpty(other, true) ?
                    " ORDER BY " + queryFieldNames.substring(0, queryFieldNames.indexOf(",")) : other;
            return queryIdNames(httpService, constructGetSql(table, queryFieldNames, where, orderStr));
        }
    
        /**
         * 从指定的数据库表中获取数据，并组成IdName数组.
         *
         * @param SQLStr 用来从DB中查询出数据并可组织成合法的ComboItem数组的完整可执行SQL语句
         *               ，形如：select id,name from t where some='any'，等，注意查询列：一般为2个字段，前一
         *               个作为ID，后一个作为Name（特殊情况下：当只有1列时（如:select id from t跟select id,id from t
         *               是一样效果），则认为该列即是ID也是Name；当列多于2个时其它列会被忽略）
         * @return 返回据指定语句查询出的数据构造成的IdName数组
         * @see IdName
         * @see #queryData(HttpService4A, String)
         * @see #constructIdNames(Vector)
         */
        public static IdName[] queryIdNames(HttpService4A httpService, String SQLStr) {
            Vector vecs = queryData(httpService, SQLStr);
            if (vecs == null)
                return null;
            else if (vecs.size() == 0)
                return new IdName[]{};
            IdName[] items = new IdName[vecs.size()];
            items = constructIdNames(vecs);
            return items;
        }
    
        /**
         * 据指定格式的vector(格式：Vector<Vector<id,name>>)组织成ComboItem 数组.
         *
         * @param itemsVec itemsVec的每个子元素也是是一个包含二个元素的Vector：索引0为ID,索引1为Name（特殊情况下：
         *                 当子Vector只有一个元素时，则认为该元素即是ID也是Name；当子Vector多于2个元素时其它会被忽略）
         * @return
         * @see IdName
         */
        public static IdName[] constructIdNames(Vector<Vector> itemsVec) {
            if (itemsVec == null || itemsVec.size() == 0)
                return new IdName[]{};
            IdName[] citems = new IdName[itemsVec.size()];
    
            //取样第一行看看是否是单列（这种情况它即是ID也是Name了）
            boolean oneColumn = itemsVec.get(0).size() == 1;
            Vector row;
            for (int i = 0; i < itemsVec.size(); i++) {
                row = itemsVec.get(i);
                Object id = row.get(0), name = oneColumn ? id//只有1列，则认为ID就是Name了
                        : row.get(1);
                citems[i] = new IdName(id, name);
            }
            return citems;
        }
    
        /**
         * 据各参数组织成一个Select语句.<br>
         * <b>重要说明：</b>本方法与EPC_dbpool中的DBUtils中的formatGetComboItemsSql方法是一模一样的，此处只是为
         * 了不让客户端程序调用服务端类方法而冗余加上的.<br>
         *
         * @param table   要查询的数据库表名（可以是诸如a join b on a.xx=b.xx等组合）
         *                ，可无表名(如调用函数时就不需要)
         * @param columns 要查询的列（多列之间用逗号分隔，形如：f1,f2,f3）
         * @param where   where条件（可无）
         * @return
         */
        public static String constructGetSql(String table, String columns, String where) {
            return constructGetSql(table, columns, where, null);
        }
    
        /**
         * 据各参数组织成一个Select语句.<br>
         * <b>重要说明：</b>本方法与EPC_dbpool中的DBUtils中的formatGetComboItemsSql方法是一模一样的，此处只是为
         * 了不让客户端程序调用服务端类方法而冗余加上的.<br>
         *
         * @param table   要查询的数据库表名（可以是诸如a join b on a.xx=b.xx等组合）
         *                ，可无表名(如调用函数时就不需要)
         * @param columns 要查询的列（多列之间用逗号分隔，形如：f1,f2,f3）
         * @param where   where条件（可无）
         * @param other   额外的SQL，如可以是order by someColumn或group by someColumn等
         * @return
         */
        public static String constructGetSql(String table, String columns
                , String where, String other) {
            StringBuffer sql = new StringBuffer("SELECT ")
                    .append(columns);
            //可无表名(如调用函数时就不需要)
            if (!CommonUtils.isStringEmpty(table))
                sql.append(" FROM ").append(table);
            //		if(where != null && where.length() > 0)
            if (!CommonUtils.isStringEmpty(where, true))
                sql.append(" WHERE ").append(where).append("  ");
            if (!CommonUtils.isStringEmpty(other, true))
                sql.append(other);
            return sql.toString();
        }
    }
}